<!DOCTYPE html>
<html>
<meta charset="utf-8">

<head>
    <link rel="stylesheet" type="text/css" href="../../resources/css/common.css" />
    <script type="text/javascript" src="../../resources/js/lib.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/big-integer/1.6.42/BigInteger.min.js">
    </script>
    <title>登录DWY的聊天室</title>
    <style>
        body {
            background-color: Plum;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        label,
        input,
        button {
            font-size: 1.5em;
        }

        div#main {
            align-self: center;
            display: flex;
            flex-flow: column nowrap;
        }

        form {
            display: flex;
            flex-flow: column nowrap;
            align-items: flex-end;
        }

        form input {
            width: 300px;
            padding: 5px;
        }

        form>div {
            display: flex;
            flex-flow: column nowrap;
        }

        form+div {
            display: flex;
            justify-content: space-between;
            flex: auto;
        }

        #iconUpload,
        input[type=file] {
            width: 80px;
            height: 80px;
        }

        #iconUpload {
            display: flex;
            background-color: PapayaWhip;
            border: inset 1px;
            flex-flow: column nowrap;
            justify-content: center;
            align-items: center;
            visibility: hidden;
            margin-left: 10px;
        }

        pre {
            font-size: 28px;
        }

        img {
            display: none;
            width: 64px;
            height: 64px;
            border-radius: 0px;
            margin: 2px;
        }

        input[type=file] {
            margin: -100% 0px 0px 0px;
        }

        button {
            width: 90px;
            height: 40px
        }

        button:not([ready]) {
            background-color: lightgray;
            color: grey;
        }

        input[name=icon] {
            display: none;
        }
    </style>
</head>

<body onload="fnBodyLoad()">
    <div id="main">
        <form id="form" method="POST" accept-charset="UTF-8" fo>
            <div>
                <label>用户名</label>
                <input id="username" name="username" maxlength="10" />
            </div>
            <div>
                <label>密码</label>
                <input id="password" name="password" type="password" maxlength="10" />
            </div>
        </form>
        <div>
            <div id="iconUpload">
                <pre>上传&#10;头像</pre>
                <img id="icon" />
                <input type="file" accept="image/*" onchange="fnIcon(this)" />
            </div>
            <div>
                <button id="reg" onclick="validateForm(this,event,'./reg')">注册</button>
                <button id="login" onclick="validateForm(this,event,'./login')" ready>登录</button>
            </div>
        </div>
    </div>
    <input form="form" name="icon" />

    <script>
        var form = document.getElementById("form");
        var iconUpload = document.getElementById("iconUpload");
        var password = document.getElementById("password");
        var btnReg = document.getElementById("reg");
        var btnLogin = document.getElementById("login");
        var iconInput = document.getElementsByName("icon")[0];


        /**
         * 页面加载
         */
        function fnBodyLoad() {
            if (fnGetCookieJson().noDB) { //未启用数据库则隐藏注册按钮
                reg.style.display = "none";
            }
        }

        /**
         * 注册或登录的操作切换
         * 操作前的前端验证、密码RSA加密
         * 
         * @param {object} btn 当前点击的按钮元素
         * @param {Event} e 点击事件
         * @param {string} actionUrl 请求地址
         */
        function validateForm(btn, e, actionUrl) {
            if (!btn.hasAttribute("ready")) { //若当前点击按钮尚未就绪，则视为切换模式
                btn.setAttribute("ready", null);
                if (btn.id == "reg") {
                    iconUpload.style.visibility = "visible";
                    btnLogin.removeAttribute("ready");
                } else {
                    iconUpload.style.visibility = "hidden";
                    btnReg.removeAttribute("ready");
                }
                return;
            }
            if (btn == btnReg) {
                if (!icon.src) {
                    alert("请上传一张头像！");
                    return;
                }
                document.getElementsByName("icon")[0].value = icon.src;
            } else {
                iconInput.value = "";
            }

            let pw = password.value;
            password.value = fnClear2CipherByRSA(pw); //对密码做RSA处理
            if (btn == btnReg) {
                btn.setAttribute("disabled", true);
                fnAjax("POST", "/reg", new FormData(form), () => {
                    password.value = pw;
                    btn.removeAttribute("disabled");
                    if (confirm("注册成功，是否立即登录？")) {
                        btnLogin.click();
                        btnLogin.click();
                    }
                }, () => {
                    password.value = pw;
                    btn.removeAttribute("disabled");
                });
            } else {
                fnAjax("POST", "/login", new FormData(form));
            }
        }


        /**
         * 将明文分段加密为RSA密文
         * 
         * @param {string} clear 原文
         * @return {string} 密文
         */
        function fnClear2CipherByRSA(clear) { //将明文加密为RSA密文
            let cookies = fnGetCookieJson();
            let codes = "";
            let l = clear.length;
            for (let i = 0; i < l; i++) {
                code = clear.charCodeAt(i).toString().padStart(3, "0"); //密码应该不用考虑中文等特殊长度的字符，视为都在ASCII范围内，约定每三位对应1个字符
                codes += code;
            }
            let blockL = cookies.module.length - 1;
            if (codes.length % blockL > 0) { //将密码ASCII串补齐到“RSA模长度-1”的整倍数，确保将原文分割成小于模的每段来处理
                codes = codes.padStart(Math.ceil(codes.length / blockL) * blockL, "0"); //注意分段规则要与服务端对应起来
            }
            let cipher = "";
            for (let i = 0, maxL = codes.length; i < maxL; i +=
                blockL) { //分段进行原文算密文，注意分割ASCII串时以模长度-1为准，但算出的密文长度还是可能达到模数的长度
                let block = bigInt(codes.substring(i, i + blockL)).modPow(cookies.pubKey, cookies
                    .module); //利用js大数库：原文**公钥 mod 模数 = 密文
                cipher += block.toString().padStart(blockL + 1, "0"); //保持位数以便服务端分段解密，此时与RSA模长度一致即可，其数值肯定是小于模数的
            }
            return cipher;
        }

        /**
         * 预览头像
         * 
         * @param {File} file 图片文件
         */
        function fnIcon(file) {
            let icon = document.getElementById("icon");
            if (fnShowImg(file, icon, 65)) {
                icon.style.display = "block";
                let pre = document.getElementsByTagName("pre")[0];
                pre.style.display = "none";
                iconInput.value = icon.src; //供表单提交的base64
            }
        }
    </script>
</body>

</html>